/* global describe: false, it: false */

var should = require("should");

module.exports = function() {
    describe("默认命名空间和 jNs 代理", function() {
        it("jNs 不是默认命名空间 jNs()", function() {
            jNs.should.not.equal(jNs());
        });

        it("jNs.name 是 'jNs'，jNs().name 是 ''", function() {
            jNs.name.should.equal("jNs");
            jNs().name.should.equal("");
        });

        it("jNs 和 jNs() 的 modules 一样", function() {
            jNs.define("first", "first");
            jNs().define("second", "second");

            var expect = ["first", "second"];
            jNs.modules.should.eql(expect);
            jNs().modules.should.eql(expect);
        });

        it("殊途同归的默认命名空间", function() {
            should.equal(jNs.using(), jNs());
            should.equal(jNs.using(), jNs().using());
        });
    });

    describe("命名空间名称", function() {
        it("命名空间的 name 总是全称", function() {
            jNs("first").name.should.equal("first");
            jNs("first.second").name.should.equal("first.second");
            jNs("first.second.third").name.should.equal("first.second.third");
        });

        it("命名空间的名称不能包含特殊字符：/[^0-9a-zA-Z_\\.]/", function() {
            var names = [
                "special.!@#$%@#",
                "special.cannot with white spaces"
            ];

            names.forEach(function(name) {
                (function() {
                    jNs(name);
                }).should.throw(/\[jNs\] unexpect character/);
            });
        });

        it("命名空间名称允许数字和下划线作为起始", function() {
            var names = [
                "special.321.begin",
                "special._.start"
            ];

            names.forEach(function(name) {
                jNs(name).name.should.equal(name, name);
            });
        });
    });

    describe("点号 '.' 是命名空间分隔符", function() {
        it("单独的 '.' 会被忽略", function() {
            jNs(".").should.equal(jNs());
        });

        it("连续 '.' 中多余的 '.' 会被忽略", function() {
            jNs("..").should.equal(jNs());
            jNs(".......").should.equal(jNs());
            jNs.using("first.....second").should.equal(jNs("first.second"));
            jNs("first.....second").should.equal(jNs("first.second"));
        });
    });

    describe("同一命名空间的多种引用方法", function() {
        it("'first.second.third' 的几种引用方法", function() {
            var ns = jNs("first.second.third");
            ns.should.equal(jNs.using("first.second.third"));
            ns.should.equal(jNs("first").using("second.third"));
            ns.should.equal(jNs("first.second").using("third"));
            ns.should.equal(jNs.using("first").using("second").using("third"));
        });

        it("'.' 是使空间分隔符", function() {
            jNs(".").name.should.equal("");
            jNs("..").name.should.equal("");
        });

        it("不支持 '.' 和 '..' 回退引用", function() {
            var ns = jNs("first.second.third");
            ns.using("..").should.not.equal(jNs("first.second"));
        });
    });

    describe("getModule 和 setModule", function() {
        it("getModule 返回一个 Module 对象", function() {
            var ns = jNs("get.set.module", function(define) {
                define("m1");
            });

            var m = ns.getModule("m1");
            m.name.should.equal("m1");
            m.ns.should.equal(ns);
        });

        it("使用 getModule 获取未定义的模块回返 undefined", function() {
            var ns = jNs("get.set.module");
            var m = ns.getModule("noneModule");
            should.equal(m, undefined);
        });

        it("setModule 将模块放入命名空间", function() {
            var ns = jNs("get.set.module");
            var Module = ns.getModule("m1").constructor;
            var m2 = new Module(ns, "m2");
            ns.putModule(m2);
            ns.modules.should.containEql("m2");
        });

        it("setModule 不能放入非 Module 对象", function() {
            var ns = jNs("get.set.module");
            (function() {
                ns.putModule(ns, {
                    name: "m3"
                });
            }).should.throw("[jNs] putModule need a Module instance");
        });

        it("setModule 不能放入已经存在的 Module", function() {
            var ns = jNs("get.set.module");

            // 已经存在的模块再次放入不会报错
            (function() {
                var m2 = ns.getModule("m2");
                ns.putModule(m2);
            }).should.not.throw();

            // 书橱存在名称相同的模块，抛出异常
            (function() {
                var Module = ns.getModule("m1").constructor;
                var duplicateM2 = new Module(ns, "m2");
                ns.putModule(duplicateM2);
            }).should.throw("[jNs] duplicate module [m2]");
        });
    });
};
